---
title: "模块 11: 编写 Pythonic 代码"
description: "学习如何编写地道、优雅且高效的 Python 代码，真正像一个 Python 开发者一样思考。"
---

## 1. 引言

每种编程语言都有其独特的风格和哲学。“Pythonic”这个词用来描述那些遵循 Python 社区公认的最佳实践、充分利用语言特性、代码简洁易读且高效的代码风格。

对于从 JavaScript 过来的开发者来说，仅仅掌握语法是不够的。学习编写 Pythonic 代码，意味着要开始用“Python 的方式”去思考和解决问题。

> 💡 **学习策略**：将编写 Pythonic 代码看作是学习一门语言的“习语”和“俚语”。它能让你的代码更受社区欢迎，也更易于他人理解和维护。

## 2. 列表推导式 (List Comprehensions)

列表推导式是 Python 中最具代表性的特性之一。它提供了一种简洁优雅的方式来根据现有列表创建新列表，通常比使用 `map()` 和 `filter()` 更具可读性。

<PythonEditor title="列表推导式 vs. map/filter" compare={true}>
```javascript !! js
// JavaScript (map and filter)
const numbers = [1, 2, 3, 4, 5];

// 获取所有数字的平方
const squares = numbers.map(n => n * n);

// 获取所有偶数的平方
const evenSquares = numbers
  .filter(n => n % 2 === 0)
  .map(n => n * n);
console.log(numbers);
console.log(squares);
console.log(evenSquares);
```

```python !! py
# Python (List Comprehensions)
numbers = [1, 2, 3, 4, 5]

# 获取所有数字的平方 (Pythonic)
squares = [n * n for n in numbers]

# 获取所有偶数的平方 (Pythonic)
even_squares = [n * n for n in numbers if n % 2 == 0]

# 非 Pythonic 的方式
even_squares_long = list(map(lambda n: n * n, filter(lambda n: n % 2 == 0, numbers)))
print(numbers)
print(squares)
print(even_squares)
print(even_squares_long)
```
</PythonEditor>

## 3. EAFP vs LBYL

这是两种不同的编程风格，Python 社区普遍推崇 EAFP。

*   **LBYL (Look Before You Leap)**: “三思而后行”。在执行操作前，先进行各种检查。这在 JavaScript 中很常见。
*   **EAFP (Easier to Ask for Forgiveness than Permission)**: “先斩后奏”。直接尝试执行操作，如果出现问题（异常），再进行处理。

<PythonEditor title="EAFP vs. LBYL 对比" compare={true}>
```javascript !! js
// JavaScript (LBYL 风格)
const user = { profile: { name: 'Alice' } };

if (user && user.profile && user.profile.name) {
  console.log(user.profile.name);
} else {
  console.log('Name not found');
}

// 使用可选链操作符 ?. 更简洁
console.log(user?.profile?.name || 'Name not found');
```

```python !! py
# Python (EAFP 风格 - Pythonic)
user = {"profile": {"name": "Alice"}}

try:
    print(user["profile"]["name"])
except (KeyError, TypeError):
    print("Name not found")

# Python (LBYL 风格 - 不那么 Pythonic)
if "profile" in user and isinstance(user["profile"], dict) and "name" in user["profile"]:
    print(user["profile"]["name"])
else:
    print("Name not found")
```
</PythonEditor>

## 4. 使用 `enumerate` 进行迭代

当你在循环中同时需要索引和值时，不要使用 `range(len(my_list))`。Pythonic 的方式是使用内置函数 `enumerate`。

<PythonEditor title="enumerate vs. range(len(...))" compare={true}>
```javascript !! js
// JavaScript
const items = ['a', 'b', 'c'];

items.forEach((item, index) => {
  console.log(`Index: ${index}, Item: ${item}`);
});
```

```python !! py
# Python (Pythonic)
items = ['a', 'b', 'c']

for index, item in enumerate(items):
    print(f"Index: {index}, Item: {item}")

# Python (不那么 Pythonic)
for i in range(len(items)):
    print(f"Index: {i}, Item: {items[i]}")
```
</PythonEditor>

## 5. 解包 (Unpacking)

Python 允许你将一个可迭代对象（如列表或元组）的元素“解包”到多个变量中。这使得代码更加简洁。

<PythonEditor title="解包 vs. 手动赋值" compare={true}>
```javascript !! js
// JavaScript (解构赋值)
const point = [10, 20, 30];
const [x, y, z] = point;

const [first, ...rest] = [1, 2, 3, 4];
// first = 1, rest = [2, 3, 4]

console.log(x, y, z);
console.log(first, rest);
```

```python !! py
# Python (解包)
point = (10, 20, 30)
x, y, z = point

# 星号表达式 (类似 JS 的 rest)
first, *rest, last = [1, 2, 3, 4, 5]
# first = 1, rest = [2, 3, 4], last = 5

print(x, y, z)
print(first, rest)
```
</PythonEditor>

## 6. 使用 `with` 语句管理资源

正如在“常见陷阱”模块中提到的，使用 `with` 语句（上下文管理器）是处理需要显式关闭的资源（如文件、数据库连接）的最 Pythonic 的方式。它能确保资源即使在发生错误时也能被正确释放。

<PythonEditor title="with 语句 vs. try...finally" compare={true} canRun={false}>
```javascript !! js
// JavaScript (没有直接对应物，通常用 try...finally)
let resource;
try {
  resource = acquireResource();
  // use resource
} finally {
  if (resource) {
    releaseResource(resource);
  }
}
```

```python !! py
# Python (Pythonic)
with open("my_file.txt", "r") as f:
    content = f.read()
    # 文件会自动关闭，即使在读取时发生错误

# Python (不那么 Pythonic)
f = open("my_file.txt", "r")
try:
    content = f.read()
finally:
    f.close()
```
</PythonEditor>

## 7. 总结

编写 Pythonic 代码是一个持续的过程，它关乎于代码的可读性、简洁性和效率。当你开始自然地使用列表推导式、`enumerate` 和 `with` 语句时，你就真正走上了成为一名地道 Python 开发者的道路。

**核心原则**：代码首先是写给人看的，其次才是给机器执行的。Pythonic 的代码正是这一原则的最佳体现。
